﻿using System.Collections.Generic;
using BalanceManagerApp.DataAccess;
using BalanceManagerApp.Model;
using BalanceManagerApp.ViewModel;
using Moq;
using NUnit.Framework;

namespace Tests
{
    [TestFixture]
    class MainWindowViewModelFixture
    {
        [Test]
        public void SetNewCurrentWorkspace()
        {
            var mainWindowViewModel = new MainWindowViewModel();            
            var stubViewModel = new StubbedViewModel();
            var propertyChangedCalled = false;
            mainWindowViewModel.PropertyChanged += delegate { propertyChangedCalled = true; };

            mainWindowViewModel.CurrentWorkspace = stubViewModel;

            Assert.AreEqual(stubViewModel, mainWindowViewModel.CurrentWorkspace, "Текущий ViewModel не соответствует тому, что был ранее присвоен");            
            Assert.AreEqual(true, propertyChangedCalled, "Событие PropertyChanged объекта MainWindowViewModel НЕ вызвано");
        }

        [Test]
        public void DisposesPreviousWorkspaceWhenSetCurrentWorkspace()
        {
            var mainWindowViewModel = new MainWindowViewModel();
            var prevViewModel = new StubbedViewModel();
            var newViewModel = new StubbedViewModel();

            mainWindowViewModel.CurrentWorkspace = prevViewModel;
            mainWindowViewModel.CurrentWorkspace = newViewModel;

            Assert.AreEqual(true, prevViewModel.IsDisposed, "Предыдущий Workspace не очищен");
        }

        [Test]
        public void DoesNothingWhenSettingWorkspaceWhichAlreadyWorking()
        {
            var mainWindowViewModel = new MainWindowViewModel();
            var prevViewModel = new StubbedViewModel();
            var newViewModel = prevViewModel;
            mainWindowViewModel.CurrentWorkspace = prevViewModel;

            // Проверка PropertyCHanged должна проводится только при присваивании newViewModel
            var propertyChangedCalled = false;
            mainWindowViewModel.PropertyChanged += delegate { propertyChangedCalled = true; };
            
            mainWindowViewModel.CurrentWorkspace = newViewModel;

            Assert.AreEqual(false, prevViewModel.IsDisposed, "Сохраненный Workspace не должен быть уничтожен");
            Assert.AreEqual(false, propertyChangedCalled, "PropertyChanged не должно быть вызвано, так как должен быть один и тот же Workspace");            
        }

        [Test]
        public void ReturnsListOfCommands()
        {
            var mainWindowViewModel = new MainWindowViewModel();

            Assert.AreEqual(5, mainWindowViewModel.Commands.Count);

            mainWindowViewModel.Commands[0].Command.Execute(null);
            Assert.IsInstanceOf<HomePageViewModel>(mainWindowViewModel.CurrentWorkspace);

            mainWindowViewModel.Commands[1].Command.Execute(null);
            Assert.IsInstanceOf<FlowFundsViewModel>(mainWindowViewModel.CurrentWorkspace);

            mainWindowViewModel.Commands[2].Command.Execute(null);
            Assert.IsInstanceOf<ReportViewModel>(mainWindowViewModel.CurrentWorkspace);

            mainWindowViewModel.Commands[3].Command.Execute(null);
            Assert.IsInstanceOf<ItemsViewModel>(mainWindowViewModel.CurrentWorkspace);

            mainWindowViewModel.Commands[4].Command.Execute(null);
            Assert.IsInstanceOf<SettingsViewModel>(mainWindowViewModel.CurrentWorkspace);            
        }

        class StubbedViewModel : WorkspaceViewModel
        {
            public bool IsDisposed { get; private set; }

            protected override void OnDispose()
            {
                this.IsDisposed = true;
                base.OnDispose();
            }
        }
    }
}
